﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class NewGameController2048 : MonoBehaviour {
	public GameObject[] myCubes;
	public GameObject[] myNumbers;
	private int randomNumber;
	private int[,] leftToRightCubeIndex;
	private int[,] RightToLeftCubeIndex;
	private int[,] UpToDownCubeIndex;
	private int[,] DownToUpCubeIndex;
	private Transform tempCube;
	private List<int> blankCubes;
	//游戏积分
	private int score = 0;
	//游戏是否结束标志位,如果不能移动而且每个格子都有数字,游戏结束
	public bool isGameOver = false;
	//所有等待移动的numberCube,先进后出,用Stack来存
	public List<GameObject> numbersWaitingForMove;
	//临时对象用来存numbersWaitingForMove中的对象
	private GameObject tempNumberCube;
	//记得删
	private Vector3 velocity = Vector3.zero;
	
	void Start ()
	{
		leftToRightCubeIndex = new int[4, 4]{	{0,1,2,3},
			{4,5,6,7},
			{8,9,10,11},
			{12,13,14,15}};
		RightToLeftCubeIndex = new int[4, 4]{	{3,2,1,0},
			{7,6,5,4},
			{11,10,9,8},
			{15,14,13,12}};
		UpToDownCubeIndex = new int[4, 4]{	{0,4,8,12},
			{1,5,9,13},
			{2,6,10,14},
			{3,7,11,15}};
		DownToUpCubeIndex = new int[4, 4]{	{12,8,4,0},
			{13,9,5,1},
			{14,10,6,2},
			{15,11,7,3}};
		//游戏初始化
		for (int i = 0; i < 4; i++) {
			randomNumber = 6;
			//			randomNumber = Random.Range (0, 16);
			if (myCubes [randomNumber].transform.childCount == 0) {
				//				InitNumberCube (i / 2, randomNumber);
				InitNumberCube (i / 2, leftToRightCubeIndex [i, 0]);
				//				InitNumberCube (0, leftToRightCubeIndex [i, 0]);
			} else if (randomNumber != 0) {
				InitNumberCube (i / 2, randomNumber - 1);
			} else {
				InitNumberCube (i / 2, randomNumber + 1);
			}
		}
		
		blankCubes = new List<int> ();
		numbersWaitingForMove = new List<GameObject> ();
		tempNumberCube = new GameObject ();
		
	}
	
	void Update ()
	{
		if (!isGameOver) {
			//按下D键,判断是否能从左往右移动,可以则移动,不可以则删除数字方块记录numberWatingForMove,再判断另外三个方向是否能移动,如果都不能,isGameOver=0,游戏结束,
			if (Input.GetKeyDown (KeyCode.D)) {
				if (CanMoveOrNot (leftToRightCubeIndex)) {
					FirstMoveCube (leftToRightCubeIndex);
					//				SecondMoveCube (leftToRightCubeIndex);
				} else if (!(CanMoveOrNot (RightToLeftCubeIndex) || CanMoveOrNot (UpToDownCubeIndex) || CanMoveOrNot (DownToUpCubeIndex))) {
					isGameOver = true;
				} 
			}
			//按下A键,判断是否能从右往左移动,可以则移动,不可以则删除数字方块记录numberWatingForMove,再判断另外三个方向是否能移动,如果都不能,isGameOver=0,游戏结束
			if (Input.GetKeyDown (KeyCode.A)) {
				if (CanMoveOrNot (RightToLeftCubeIndex)) {
					FirstMoveCube (RightToLeftCubeIndex);
					//				SecondMoveCube (RightToLeftCubeIndex);
				} else if (!(CanMoveOrNot (leftToRightCubeIndex) || CanMoveOrNot (UpToDownCubeIndex) || CanMoveOrNot (DownToUpCubeIndex))) {
					isGameOver = true;
				} 
			}
			//按下S键,判断是否能从上往下移动,可以则移动,不可以则删除数字方块记录numberWatingForMove,再判断另外三个方向是否能移动,如果都不能,isGameOver=0,游戏结束
			if (Input.GetKeyDown (KeyCode.S)) {
				if (CanMoveOrNot (UpToDownCubeIndex)) {
					FirstMoveCube (UpToDownCubeIndex);
					//				SecondMoveCube (UpToDownCubeIndex);
				} else if (!(CanMoveOrNot (leftToRightCubeIndex) || CanMoveOrNot (RightToLeftCubeIndex) || CanMoveOrNot (DownToUpCubeIndex))) {
					isGameOver = true;
				} 
			}
			//按下W键,判断是否能从下往上移动,可以则移动,不可以则删除数字方块记录numberWatingForMove,再判断另外三个方向是否能移动,如果都不能,isGameOver=0,游戏结束
			if (Input.GetKeyDown (KeyCode.W)) {
				if (CanMoveOrNot (DownToUpCubeIndex)) {
					FirstMoveCube (DownToUpCubeIndex);
					//				SecondMoveCube (DownToUpCubeIndex);
				} else if (!(CanMoveOrNot (leftToRightCubeIndex) || CanMoveOrNot (UpToDownCubeIndex) || CanMoveOrNot (RightToLeftCubeIndex))) {
					isGameOver = true;
				} 
			}
		} else {
			print ("游戏结束");
		}
		
		//移动格子
		if (numbersWaitingForMove.Count != 0) {
			//如果是null,直接删除
			if (numbersWaitingForMove [0] == null) {
				//			if (ReferenceEquals (numbersWaitingForMove [0], null) || numbersWaitingForMove [0].Equals (null)) {
				print ("Cube wait for destroy is destroy");
				numbersWaitingForMove.RemoveAt (0);
			}
			//如果格子是这次新合并的,不移动,坐标直接等于zero
			else if (numbersWaitingForMove [0].GetComponent<IndexHold> ().isCubeMove) {
				numbersWaitingForMove [0].transform.localPosition = Vector2.zero;
				numbersWaitingForMove [0].GetComponent<IndexHold> ().isCubeMove = false;
			} 
			//不然移动格子
			else {
				print ("Cube wait for destroy is NOT destroy");
				if ((numbersWaitingForMove [0].transform.localPosition - Vector3.zero).magnitude < 0.5f) {
					numbersWaitingForMove [0].transform.localPosition = Vector3.zero;
					numbersWaitingForMove.RemoveAt (0);
					
				} else {
					numbersWaitingForMove [0].transform.localPosition = Vector3.SmoothDamp (numbersWaitingForMove [0].transform.localPosition,
					                                                                        Vector3.zero, ref velocity, Time.deltaTime);
					
				}
			}
		}
	}
	
		void OnGUI()
		{
			GUI.TextArea(new Rect(200,200,200,200),score.ToString());
		}
	
	
	/// <summary>
	/// 判断是否能滑动,传入参数为滑动方向上的格子索引下标
	/// 返回true可以移动,返回false不能移动
	/// 并记录下所有有数字格子的位置,放入numberWaitingForMove
	/// </summary>
	/// <returns><c>true</c> if this instance can move or not; otherwise, <c>false</c>.</returns>
	public bool CanMoveOrNot (int[,] cubeIndex)
	{
		//需要返回的是否可移动标志位
		bool cubeCanMoveFlag = false;
		//每行遍历一次
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j <3; j++) {
				//如果遇到有数字的格子,则判断下一个格子是否为null,或者数字是否相同,相同则赋值true
				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
					//把所有数字组件丢到Stack中
					numbersWaitingForMove.Add (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
						cubeCanMoveFlag = true;
						
					} else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
						cubeCanMoveFlag = true;
					}	
				}
			}
		}
		//标示位为true,返回可移动
		if (cubeCanMoveFlag) {
			return true;
		}
		//遍历完了,标识位不为true则返回不能移动,同时删除numberWaitingForMove中所有元素
		else {
			numbersWaitingForMove.Clear ();
			return false;
		}
		
	}
	/// <summary>
	/// 遇到有数字的格子,则判断下一个格子是否为null,为null则移动到下一格
	/// 数字相同则何为一个,
	/// 传入参数为滑动方向上的格子索引
	/// </summary>
	public void FirstMoveCube (int[,] cubeIndex)
	{
		#region 遍历三遍,将数字都放到一边,但是不相加
		for (int k = 0; k < 3; k++) {
			
			
			for (int i = 0; i < 4; i++) {
				for (int j = 0; j <3; j++) {
					if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
						if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
							myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
							//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
						} 
						//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
						//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
						//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
						//					}	
					} 
				}
			}
		}
		//		for (int i = 0; i < 4; i++) {
		//			for (int j = 0; j <3; j++) {
		//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
		//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
		//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
		////						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
		//					} 
		//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
		//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
		//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
		//					//					}	
		//				} 
		//			}
		//		}
		//		for (int i = 0; i < 4; i++) {
		//			for (int j = 0; j <3; j++) {
		//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
		//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
		//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
		////						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
		//					} 
		//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
		//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
		//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
		//					//					}	
		//				}
		//			}
		//		}
		#endregion
		#region 从后往前遍历,如果数字相同就合并相加
		//每行遍历一次
		for (int i = 0; i < 4; i++) {
			for (int j = 3; j > 0; j--) {
				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
					////					判断这个格子是不是这次滑动新加的,如果是则不判断他的下一格,如果不是则判断下一个格子是否为null,或者数字是否相同
					//					if (myCubes [cubeIndex [i, j]].transform.GetChild (0).GetComponent<IndexHold> ().isCubeMove) {
					//						myCubes [cubeIndex [i, j]].transform.GetChild (0).GetComponent<IndexHold> ().isCubeMove = false;
					//					} else 
					//					if (myCubes [cubeIndex [i, j - 1]].transform.childCount == 0) {
					//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
					//					} else 
					if (myCubes [cubeIndex [i, j - 1]].transform.childCount != 0) {
						if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j - 1]].transform.GetChild (0).name) {
							DestroyImmediate (myCubes [cubeIndex [i, j - 1]].transform.GetChild (0).gameObject);
							myCubes [cubeIndex [i, j]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
							//加分
							score += (int)Mathf.Pow (2,myCubes [cubeIndex [i, j]].transform.GetChild (0).GetComponent<IndexHold> ().numberIndex);
						}
					}
				} 
				//				
			}
		}
		#endregion
		
		#region 因为有合并,再执行三次移动,同时记录空白格的位置
		//		for (int i = 0; i < 4; i++) {
		//			for (int j = 0; j <3; j++) {
		//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
		//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
		//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
		////						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
		//					} 
		//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
		//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
		//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
		//					//					}	
		//				} 
		//			}
		//		}
		//		for (int i = 0; i < 4; i++) {
		//			for (int j = 0; j <3; j++) {
		//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
		//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
		//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
		////						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
		//					} 
		//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
		//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
		//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
		//					//					}	
		//				} 
		//			}
		//		}
		for (int k = 0; k < 3; k++) {
			for (int i = 0; i < 4; i++) {
				for (int j = 0; j <3; j++) {
					if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
						if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
							myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
							//							if (myCubes [cubeIndex [i, j+1]].transform.GetChild (0).GetComponent<IndexHold> ().isCubeMove) {
							//								myCubes [cubeIndex [i, j+1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
							//							}
						} 
						//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
						//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
						//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
						//					}	
					} else if (k == 0) {
						blankCubes.Add (cubeIndex [i, j]);
					}
				}
			}
		}
		#endregion
		
		#region 在空白格上随机初始化一个2
		//随机加个2
		if (blankCubes.Count != 0) {
			randomNumber = blankCubes [Random.Range (0, blankCubes.Count)];
		} else {
			randomNumber = cubeIndex [Random.Range (0, 4), 0];
		}
		InitNumberCube (0, randomNumber);
		
		
		//空白格记录清空
		blankCubes.Clear ();
		#endregion
		
	}
	// <summary>
	// 调用FirstMoveCube之后调用
	// 遇到有数字的格子,则判断下一个格子是否为null,为null则移动到下一格
	// 注:为什么写这个函数是因为解决四个相同的数滑动BUG问题,例:2 2 2 2-> 0 4 0 4,初步怀疑是Destory函数调用时的机制问题,在Debug中并没有如预想的变为0 4 0 4,而是变成了2 4 2 4;
	// </summary>
	// <param name="cubeIndex">Cube index.</param>
	#region 写废的方法,暂时不用了
	//	public void SecondMoveCube (int[,] cubeIndex)
	//	{
	//		for (int i = 0; i < 4; i++) {
	//			for (int j = 0; j <3; j++) {
	//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
	//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
	//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
	//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
	//					} 
	//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
	//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
	//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
	//					//					}	
	//				} 
	//			}
	//		}
	//		for (int i = 0; i < 4; i++) {
	//			for (int j = 0; j <3; j++) {
	//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
	//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
	//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
	//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
	//					} 
	//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
	//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
	//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
	//					//					}	
	//				} 
	//			}
	//		}
	//		for (int i = 0; i < 4; i++) {
	//			for (int j = 0; j <3; j++) {
	//				if (myCubes [cubeIndex [i, j]].transform.childCount != 0) {
	//					if (myCubes [cubeIndex [i, j + 1]].transform.childCount == 0) {
	//						myCubes [cubeIndex [i, j]].transform.GetChild (0).transform.parent = myCubes [cubeIndex [i, j + 1]].transform;
	//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).transform.localPosition = Vector2.zero;
	//					} 
	//					//					else if (myCubes [cubeIndex [i, j]].transform.GetChild (0).name == myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).name) {
	//					//						Destroy (myCubes [cubeIndex [i, j]].transform.GetChild (0).gameObject);
	//					//						myCubes [cubeIndex [i, j + 1]].transform.GetChild (0).GetComponent<IndexHold> ().ChangNumber ();
	//					//					}	
	//				} else {
	//					blankCubes.Add (cubeIndex [i, j]);
	//				}
	//			}
	//		}
	//		//随机加个2
	//		if (blankCubes.Count != 0) {
	//			randomNumber = blankCubes [Random.Range (0, blankCubes.Count)];
	//		} else {
	//			randomNumber = cubeIndex [Random.Range (0, 4), 0];
	//		}
	//		GameObject newNumerA = Instantiate (myNumbers [0], new Vector2 (0, 0), Quaternion.identity) as GameObject;
	//		Debug.Log (blankCubes.Count);
	//		newNumerA.transform.parent = myCubes [randomNumber].transform;
	//		newNumerA.transform.localPosition = Vector2.zero;
	//		
	//		//空格记录清空
	//		blankCubes.Clear ();
	//	}
	#endregion
	
	/// <summary>
	/// 创建数字方块
	/// 参数:Number index.数字的下标
	/// Cube index.创建方块的下标
	/// </summary>
	/// <param name="numberIndex">Number index.数字的下标</param>
	/// <param name="cubeIndex">Number index.数字的下标</param>
	public void InitNumberCube (int numberIndex, int cubeIndex)
	{
		GameObject newNumerCube = Instantiate (myNumbers [numberIndex], new Vector2 (0, 0), Quaternion.identity) as GameObject;
		newNumerCube.transform.parent = myCubes [cubeIndex].transform;
		newNumerCube.transform.localPosition = Vector2.zero;
		newNumerCube.GetComponent<Animation> ().CrossFade ("InitNumber");
	}
}
